using System;
using System.Collections.Generic;
using System.Data;
using AIFSContentManagementSystem;
using AIFSDataAccessLayer.Utilities;

namespace AIFSCMS.Infrastructure.EntityMappers
{
    public abstract class EntityMapper<T> where T : ModelBase, new()
    {
        public List<T> Map(DataTable dtEntity)
        {
            List<T> dtos = new List<T>();

            if (dtEntity == null || dtEntity.Rows.Count == 0)
                return dtos;            

            foreach (DataRow drEntity in dtEntity.Rows)
            {
                T dto = this.Map(drEntity);
                dtos.Add(dto);
            }

            return dtos;
        }

        public T MapSingleRow(DataTable dtEntity)
        {
            if (dtEntity == null || dtEntity.Rows.Count == 0)
                return null;

            return Map(dtEntity.Rows[0]);
        }

        private T Map(DataRow drEntity)
        {
            if (drEntity == null)
            {
                return null;
            }

            T dto = new T();
            
            try
            {
                dto.CreateTimestamp = DataTableUtil.ToDateTimeType(drEntity, "CREATE_TIMESTAMP");
                dto.LastTimestamp = DataTableUtil.ToDateTimeType(drEntity, "LAST_TIMESTAMP");
                dto.CreateUserId = DataTableUtil.ToStringType(drEntity, "CREATE_USER_ID");
                dto.LastUserId = DataTableUtil.ToStringType(drEntity, "LAST_USER_ID");
                
                Map(drEntity, dto);

                return dto;
            }
            catch (AIFSCMSInfrastructureException aex)
            {
                throw aex;
            }
            catch (Exception ex)
            {
                throw new AIFSCMSInfrastructureException(string.Format("Error occured when mapping from the data source for {0}", dto.GetType().Name), ex);
            }
        }

        /// <summary>
        /// Implement this in the derieved classes to populate specific fields
        /// </summary>
        /// <param name="drEntity"></param>
        /// <param name="dto"></param>
        protected abstract void Map(DataRow drEntity, T dto);
    }
}
